package org.chen.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.chen.enu.TaskStatus;
import org.chen.exception.ErrorContext;
import org.chen.mapper.CommentTaskMapper;
import org.chen.model.CommentTask;
import org.chen.model.RetryMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class CommentErrorHandlerService {

    @Value("${comment.max-retries:3}")
    private int maxRetries;

    @Autowired
    private CommentTaskMapper taskMapper;

    @Autowired
    private BatchStatsManager batchStatsManager;

    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    /**
     * 统一错误分析和处理方法
     */
    public ErrorContext analyzeError(Throwable error) {
        // SSL相关错误
        if (error instanceof javax.net.ssl.SSLHandshakeException) {
            String message = error.getMessage();
            if (message.contains("No subject alternative DNS name")) {
                return ErrorContext.fatalError("SSL证书域名验证失败: " + extractDomainFromError(message));
            }
            if (message.contains("Remote host terminated")) {
                return ErrorContext.fatalError("SSL连接被远程主机终止");
            }
            if (message.contains("PKIX path validation failed") ||
                    message.contains("validity check failed")) {
                return ErrorContext.fatalError("SSL证书验证失败: 证书无效或过期");
            }
            return ErrorContext.fatalError("SSL证书错误: " + message);
        }

        // HTTP错误
        if (error instanceof org.jsoup.HttpStatusException httpError) {
            return ErrorContext.httpError(httpError.getStatusCode(), httpError.getUrl());
        }

        String message = error.getMessage();
        if (message == null) {
            return ErrorContext.fatalError("未知错误");
        }

        // 读取超时错误
        if (message.contains("Read timed out") || message.contains("Read timeout") || message.contains("ReadTimeoutException")) {
            return ErrorContext.fatalError("获取页面内容失败: 读取超时");
        }

        // 业务错误
        if (message.contains("Comment form not found")) {
            return ErrorContext.fatalError("评论表单未找到");
        }
        if (message.contains("Comment execution failed")) {
            return ErrorContext.fatalError("评论执行失败，可能需要登录");
        }
        if (message.contains("document not found")) {
            return ErrorContext.fatalError("获取页面内容失败");
        }

        // 其他网络错误 - 可重试
        if (message.contains("Connection refused")) {
            return ErrorContext.networkError("连接被拒绝");
        }
        if (message.contains("Network is unreachable")) {
            return ErrorContext.networkError("网络不可达");
        }
        if (message.contains("Connection reset")) {
            return ErrorContext.networkError("连接被重置");
        }
        if (message.contains("Connection timed out")) {
            return ErrorContext.networkError("连接超时");
        }

        if (message.contains("CONFLICT")) {
            return ErrorContext.networkError("评论冲突");
        }

        if (message.contains("FORBIDDEN")) {
            return ErrorContext.networkError("评论被拒");
        }

        // 添加服务器意外断开连接的错误处理
        if (message.contains("Unexpected end of file from server")) {
            return ErrorContext.fatalError("获取页面失败：服务器意外断开连接");
        }

        // 添加服务器提前关闭连接的错误处理
        if (message.contains("Connection prematurely closed") ||
                message.contains("PrematureCloseException")) {
            return ErrorContext.fatalError("获取页面失败：服务器提前关闭连接");
        }

        if (message.contains("TOO_MANY_REQUESTS")) {
            return ErrorContext.networkError("请求过多");
        }

        if (message.contains("INTERNAL_SERVER_ERROR")) {
            return ErrorContext.fatalError("评论时目标服务器错误");
        }

        if (message.contains("NOT_ACCEPTABLE")){
            return ErrorContext.fatalError("评论表单的不可接受（NOT_ACCEPTABLE）");
        }
        if (message.contains("Underlying input stream returned zero bytes")) {
            return ErrorContext.fatalError("获取页面失败：服务器未返回任何数据");
        }

        if (message.contains("Cannot invoke")) {
            return ErrorContext.networkError("没有返回值");
        }

        if (message.contains("NOT_FOUND")){
            return ErrorContext.fatalError("未找到");
        }

        if (message.contains("Failed to fetch page content")){
            return ErrorContext.fatalError("无法获取页面内容");
        }
        if (message.contains("handshake timed out after")){
            return ErrorContext.fatalError("握手超时");
        }
        if (message.contains("dns")){
            return ErrorContext.fatalError("网站Dns解析异常");
        }

        return ErrorContext.fatalError("未预期的错误: " + message);
    }

    /**
     * 从错误消息中提取域名
     */
    private String extractDomainFromError(String message) {
        if (message.contains("DNS name matching")) {
            try {
                return message.split("matching")[1].split("found")[0].trim();
            } catch (Exception e) {
                return "unknown domain";
            }
        }
        return "unknown domain";
    }

    /**
     * 统一的错误处理入口
     */
    public void handleTaskError(CommentTask task, ErrorContext errorContext) {
        try {
            log.error("error:{}", errorContext.message);
            if (errorContext.retryable && task.getRetryCount() < maxRetries) {
                scheduleRetry(task, errorContext.message);
            } else {
                task.setStatus(TaskStatus.FAILED.name());
                task.setErrorMessage(errorContext.message);
                task.setUpdateTime(LocalDateTime.now());
                taskMapper.updateById(task);

                batchStatsManager.incrementCounter(task.getBatchNo(), false);
            }
        } catch (Exception e) {
            log.error("Error handling task error: {}", e.getMessage());
            markAsFailed(task, "错误处理失败: " + e.getMessage());
        }
    }

    /**
     * 标记任务失败
     */
    private void markAsFailed(CommentTask task, String errorMessage) {
        task.setErrorMessage(errorMessage);
        task.setStatus(TaskStatus.FAILED.name());
        task.setRetryCount(maxRetries); // 防止重试
        task.setUpdateTime(LocalDateTime.now());
        taskMapper.updateById(task);

        batchStatsManager.incrementCounter(task.getBatchNo(), false);

        // 更新批次进度
        batchStatsManager.updateBatchProgress(task.getBatchNo());

        log.error("Task {} failed: {}", task.getId(), errorMessage);
    }

    /**
     * 安排重试
     */
    private void scheduleRetry(CommentTask task, String errorMessage) {
        task.setRetryCount(task.getRetryCount() + 1);
        task.setStatus(TaskStatus.PENDING.name());
        task.setErrorMessage(errorMessage);
        task.setUpdateTime(LocalDateTime.now());
        taskMapper.updateById(task);

        // 计算递增的重试延迟
        long retryDelay = calculateRetryDelay(task.getRetryCount());

        RetryMessage message = RetryMessage.builder()
                .taskId(task.getId())
                .batchNo(task.getBatchNo())
                .retryCount(task.getRetryCount())
                .delayMillis(retryDelay)
                .build();

        rocketMQTemplate.syncSend("comment_retry_topic", message, retryDelay);
        log.info("Scheduled retry {} for task {}", task.getRetryCount(), task.getId());
    }

    /**
     * 计算重试延迟
     */
    private long calculateRetryDelay(int retryCount) {
        // 使用指数退避策略
        return TimeUnit.MINUTES.toMillis(5) * (1L << (retryCount - 1));
    }
}
